package pers.cz.netty.protocal;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageEncoder;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List;

/**
 * @program: JefLogTail
 * @description: UDP传输时的编码方式
 * @author: Cheng Zhi
 * @create: 2023-03-29 15:04
 **/
public class UdpMessageEncoder extends MessageToMessageEncoder<Message> {

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List<Object> list) throws Exception {

        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
        // 写入魔数
        byteBuf.writeBytes(ProtocalConst.POCKET_MAGIC_NUM.getBytes());
        // 写入消息类型
        byteBuf.writeByte(message.getMsgType().type());
        // 写入附件信息
        byteBuf.writeShort(message.getAttachments().size());	// 写入当前消息的附加参数数量
        message.getAttachments().forEach((key, value) -> {
            Charset charset = Charset.defaultCharset();
            byteBuf.writeInt(key.length());	// 写入键的长度
            byteBuf.writeCharSequence(key, charset);	// 写入键数据
            byteBuf.writeInt(value.length());	// 写入值的长度
            byteBuf.writeCharSequence(value, charset);	// 写入值数据
        });
        // 写入消息长度和数据内容
        final Object content = message.getContent();
        if (content == null) {
            byteBuf.writeLong(0L);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(content);
            byte[] bytes = bos.toByteArray();
            byteBuf.writeLong(bytes.length);
            // 主体消息
            byteBuf.writeBytes(bytes);
        }

        InetSocketAddress remoteAddress = new InetSocketAddress(message.getIp(), message.getPort());
        DatagramPacket packet = new DatagramPacket(byteBuf, remoteAddress);
        list.add(packet);
    }
}
